* Xen guest identifier and loader selection
*/
.section __xen_guest
- .asciz "GUEST_OS=netbsd,GUEST_VER=2.0,XEN_VER=2.0,LOADER=generic"
+ .ascii "GUEST_OS=netbsd,GUEST_VER=2.0,XEN_VER=2.0"
+ .ascii ",LOADER=generic"
+#if (NKSYMS || defined(DDB) || defined(LKM)) && !defined(SYMTAB_SPACE)
+ .ascii ",BSD_SYMTAB"
+#endif
+ .byte 0
/*
.data
.globl _C_LABEL(cpu)
- .globl _C_LABEL(esym),_C_LABEL(boothowto)
+ .globl _C_LABEL(boothowto)
.globl _C_LABEL(bootinfo),_C_LABEL(atdevbase)
#ifdef COMPAT_OLDBOOT
.globl _C_LABEL(bootdev)
_C_LABEL(cpu): .long 0 # are we 386, 386sx, or 486,
# or Pentium, or..
-_C_LABEL(esym): .long 0 # ptr to end of syms
_C_LABEL(atdevbase): .long 0 # location of start of iomem in virtual
_C_LABEL(proc0paddr): .long 0
_C_LABEL(PTDpaddr): .long 0 # paddr of PTD, for libkvm
#define _RELOC(x) ((x))
#define RELOC(x) _RELOC(_C_LABEL(x))
-/* XXX assym.h */
-#define MOD_START 48
-#define MOD_LEN 56
-/* XXX assym.h */
-
.text
.globl _C_LABEL(kernel_text)
.set _C_LABEL(kernel_text),KERNTEXTOFF
movl %esi,%ebx # save start_info pointer
-#if (NKSYMS || defined(DDB) || defined(LKM)) && !defined(SYMTAB_SPACE)
- /* Save the symbol locations. */
- movl MOD_START(%ebx),%esi
- addl MOD_LEN(%ebx),%esi
- movl %esi,RELOC(esym)
-#endif
-
/* Clear BSS first so that there are no surprises... */
xorl %eax,%eax
movl $RELOC(__bss_start),%edi
struct domain_setup_info
{
unsigned long v_start;
+ unsigned long v_end;
unsigned long v_kernstart;
unsigned long v_kernend;
unsigned long v_kernentry;
unsigned int use_writable_pagetables;
+ unsigned int load_bsd_symtab;
+
+ unsigned long symtab_addr;
+ unsigned long symtab_len;
};
static int parseelfimage(char *elfbase,
struct domain_setup_info *dsi);
static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray,
unsigned long vstart);
+static int loadelfsymtab(char *elfbase, void *pmh, unsigned long *parray,
+ struct domain_setup_info *dsi);
static long get_tot_pages(int xc_handle, u32 domid)
{
xc_domain_setvmassist(xc_handle, dom, VMASST_CMD_enable,
VMASST_TYPE_writable_pagetables);
+ if (dsi.load_bsd_symtab)
+ loadelfsymtab(image, NULL, NULL, &dsi);
+
if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
{
PERROR("Guest OS must load to a page boundary.\n");
* read-only). We have a pair of simultaneous equations in two unknowns,
* which we solve by exhaustive search.
*/
+ vinitrd_start = round_pgup(dsi.v_end);
+ vinitrd_end = vinitrd_start + initrd_len;
+ vphysmap_start = round_pgup(vinitrd_end);
+ vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
+ vpt_start = round_pgup(vphysmap_end);
for ( nr_pt_pages = 2; ; nr_pt_pages++ )
{
- vinitrd_start = round_pgup(dsi.v_kernend);
- vinitrd_end = vinitrd_start + initrd_len;
- vphysmap_start = round_pgup(vinitrd_end);
- vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
- vpt_start = round_pgup(vphysmap_end);
vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
vstartinfo_start = vpt_end;
vstartinfo_end = vstartinfo_start + PAGE_SIZE;
loadelfimage(image, pm_handle, page_array, dsi.v_start);
+ if (dsi.load_bsd_symtab)
+ loadelfsymtab(image, pm_handle, page_array, &dsi);
+
/* Load the initial ramdisk image. */
if ( initrd_len != 0 )
{
if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL )
dsi->use_writable_pagetables = 1;
+ if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
+ dsi->load_bsd_symtab = 1;
+
dsi->v_kernstart = kernstart;
dsi->v_kernend = kernend;
dsi->v_kernentry = ehdr->e_entry;
+ dsi->v_end = dsi->v_kernend;
+
return 0;
}
return 0;
}
+static void map_memcpy(unsigned long dst, char *src, unsigned long size,
+ void *pmh, unsigned long *parray, unsigned long vstart)
+{
+ char *va;
+ unsigned long chunksz, done, pa;
+
+ for ( done = 0; done < size; done += chunksz )
+ {
+ pa = dst + done - vstart;
+ va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]);
+ chunksz = size - done;
+ if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
+ chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
+ memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
+ unmap_pfn(pmh, va);
+ }
+}
+
+#define ELFROUND (ELFSIZE / 8)
+
+static int loadelfsymtab(char *elfbase, void *pmh, unsigned long *parray,
+ struct domain_setup_info *dsi)
+{
+ Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr;
+ Elf_Shdr *shdr;
+ unsigned long maxva, symva;
+ char *p;
+ int h, i;
+
+ p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
+ ehdr->e_shnum * sizeof(Elf_Shdr));
+ if (p == NULL)
+ return 0;
+
+ maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
+ symva = maxva;
+ maxva += sizeof(int);
+ dsi->symtab_addr = maxva;
+ dsi->symtab_len = 0;
+ maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
+ maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+
+ shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
+ memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
+
+ for ( h = 0; h < ehdr->e_shnum; h++ )
+ {
+ if ( shdr[h].sh_type == SHT_STRTAB )
+ {
+ /* Look for a strtab @i linked to symtab @h. */
+ for ( i = 0; i < ehdr->e_shnum; i++ )
+ if ( (shdr[i].sh_type == SHT_SYMTAB) &&
+ (shdr[i].sh_link == h) )
+ break;
+ /* Skip symtab @h if we found no corresponding strtab @i. */
+ if ( i == ehdr->e_shnum )
+ {
+ shdr[h].sh_offset = 0;
+ continue;
+ }
+ }
+
+ if ( (shdr[h].sh_type == SHT_STRTAB) ||
+ (shdr[h].sh_type == SHT_SYMTAB) )
+ {
+ if ( pmh != NULL )
+ map_memcpy(maxva, elfbase + shdr[h].sh_offset, shdr[h].sh_size,
+ pmh, parray, dsi->v_start);
+
+ /* Mangled to be based on ELF header location. */
+ shdr[h].sh_offset = maxva - dsi->symtab_addr;
+
+ dsi->symtab_len += shdr[h].sh_size;
+ maxva += shdr[h].sh_size;
+ maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+ }
+
+ shdr[h].sh_name = 0; /* Name is NULL. */
+ }
+
+ if ( dsi->symtab_len == 0 )
+ {
+ dsi->symtab_addr = 0;
+ goto out;
+ }
+
+ if ( pmh != NULL ) {
+ *(int *)p = maxva - dsi->symtab_addr;
+ sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
+ memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
+ sym_ehdr->e_phoff = 0;
+ sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
+ sym_ehdr->e_phentsize = 0;
+ sym_ehdr->e_phnum = 0;
+ sym_ehdr->e_shstrndx = SHN_UNDEF;
+
+ /* Copy total length, crafted ELF header and section header table */
+ map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
+ ehdr->e_shnum * sizeof(Elf_Shdr), pmh, parray,
+ dsi->v_start);
+ }
+
+ dsi->symtab_len = maxva - dsi->symtab_addr;
+ dsi->v_end = round_pgup(maxva);
+
+ out:
+ if ( p != NULL )
+ free(p);
+
+ return 0;
+}